package org.apache.ibatis.session;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.io.Resources;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class SqlSessionFactoryBuilder {
	//建造者模式
	//用于保存每一条select语句（每1条sql包含id,输入参数，输出参数，sql本身）
	private Map<String,SelectStatement> selectStatementMap = new HashMap<String,SelectStatement>();
	
	public SqlSessionFactory build(InputStream inputStream){
		//System.out.println(inputStream);
		
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactory();
		SAXReader reader = new SAXReader();
		try {
			//拿到doc对象后，就拥有操作这份XML文件一切权限
			Document doc = reader.read(inputStream);
			Element rootElement = doc.getRootElement();
			Element environments_element =(Element) rootElement.selectSingleNode("/configuration/environments");
			String default_env = environments_element.attributeValue("default");
			Element current_env_element =(Element)environments_element.selectSingleNode("environment[@id='"+default_env+"']");
			Element dataSource_element =(Element)current_env_element.selectSingleNode("dataSource");
			//这4个就是我们目标节点
			Element p_driver =(Element)dataSource_element.selectSingleNode("property[@name='driver']");
			Element p_url =(Element)dataSource_element.selectSingleNode("property[@name='url']");
			Element p_username =(Element)dataSource_element.selectSingleNode("property[@name='username']");
			Element p_password =(Element)dataSource_element.selectSingleNode("property[@name='password']");
			
			String driver = p_driver.attributeValue("value");
			String url = p_url.attributeValue("value");
			String username = p_username.attributeValue("value");
			String password = p_password.attributeValue("value");
			
			
			List<Element> mapperList = rootElement.selectNodes("/configuration/mappers/mapper");
			for(Element mapperElement:mapperList){
				String mapperResource = mapperElement.attributeValue("resource");
				//进一步解析2个Mapper文件
				dealMapperFile(mapperResource);
				
			}
			
			System.out.println("建造者Builder解析sqlMapConfig.xml");
			System.out.println(driver);
			System.out.println(url);
			System.out.println(username);
			System.out.println(password);
			sqlSessionFactory.setDriver(driver);
			sqlSessionFactory.setUrl(url);
			sqlSessionFactory.setUsername(username);
			sqlSessionFactory.setPassword(password);
			sqlSessionFactory.setSelectStatementMap(selectStatementMap);
			
			
			System.out.println("生成一个SqlSessionFactory对象，然后赋值");
			inputStream.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return sqlSessionFactory;
	}
	
	
	public SqlSessionFactory build() throws Exception{
		throw new Exception("没有实现的，请勿使用"); 
	}
	
	//解析mapper文件
	public void dealMapperFile(String fileName){
		InputStream inputStream = SqlSessionFactoryBuilder.class.getClassLoader().getResourceAsStream(fileName);
		SAXReader reader = new SAXReader();
		try {
			Document doc_mapper = reader.read(inputStream);
			Element mapperElement = doc_mapper.getRootElement();
			String namespace = mapperElement.attributeValue("namespace");
			//System.out.println(namespace);
			List<Element> selectList = mapperElement.selectNodes("/mapper/select");
			for(Element selectElement:selectList){
				String id = selectElement.attributeValue("id");
				String parameterType = selectElement.attributeValue("parameterType");
				String resultType = selectElement.attributeValue("resultType");
				String sqltext = selectElement.getText().trim();
				//System.out.println(id+" "+ parameterType+" "+resultType+" "+sqltext);
				SelectStatement selectStatement = new SelectStatement();
				selectStatement.setId(id);
				selectStatement.setParameterType(parameterType);
				selectStatement.setResultType(resultType);
				selectStatement.setSqltext(sqltext);
				selectStatementMap.put(namespace+"."+id, selectStatement);
			}
			inputStream.close();
		} catch (Exception e1) {			
			e1.printStackTrace();
		}
	}
}
